package com.smart.community.region.service.impl;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import com.smart.community.commons.exception.BusinessException;
import com.smart.community.commons.enums.RoleCodeEnum;
import com.smart.community.commons.enums.SystemStatusEnum;
import com.smart.community.commons.utils.SecurityUtils;
import com.smart.community.feign.user.dto.NormalUserCreateDTO;
import com.smart.community.feign.user.dto.UserDTO;
import com.smart.community.feign.user.service.UserFeignService;
import com.smart.community.region.dto.OwnerDTO;
import com.smart.community.region.entity.Owner;
import com.smart.community.region.entity.OwnerHousehold;
import com.smart.community.region.service.IOwnerHouseholdService;
import com.smart.community.region.service.IOwnerService;
import com.smart.community.region.service.OwnerProcessingService;

import lombok.extern.slf4j.Slf4j;

/**
 * 业主信息处理服务实现类
 * 负责业主信息的新增、更新、手机号一致性检查和房户关联关系建立
 * 
 * @author Wu.Liang
 * @since 2025-08-22
 * @version 1.0.0
 */
@Slf4j
@Service
public class OwnerProcessingServiceImpl implements OwnerProcessingService {
    
    @Autowired
    private IOwnerService ownerService;
    
    @Autowired
    private IOwnerHouseholdService ownerHouseholdService;
    
    @Autowired
    private UserFeignService userFeignService;
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Owner processOwnerInfo(OwnerDTO ownerDTO) throws Exception {
        try {
            // 1. 根据身份证号查询现有业主
            Owner existingOwner = ownerService.getOwnerByIdCard(ownerDTO.getIdCard());
            
            if (existingOwner == null) {
                // 2. 不存在则新增业主（包含并发处理）
                return createNewOwner(ownerDTO);
            } else {
                // 3. 存在则更新业主信息
                return updateExistingOwner(existingOwner, ownerDTO);
            }
        } catch (Exception e) {
            log.error("处理业主信息失败，身份证号：{}", ownerDTO.getIdCard(), e);
            throw new BusinessException("处理业主信息失败：" + e.getMessage());
        }
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void createOwnerHouseholdAssociation(Long ownerId, Long householdId) throws Exception {
        try {
            // 检查是否已存在关联关系
            boolean exists = checkAssociationExists(ownerId, householdId);
            if (exists) {
                log.warn("业主房户关联关系已存在，业主ID：{}，房户ID：{}", ownerId, householdId);
                return;
            }
            
            // 创建关联关系
            OwnerHousehold association = new OwnerHousehold();
            association.setOwnerId(ownerId);
            association.setHouseholdId(householdId);
            association.setOwnershipType(1); // 完全产权
            association.setOwnershipRatio(new java.math.BigDecimal("100.00")); // 100%产权
            association.setIsPrimaryOwner(1); // 主业主
            association.setAssociationStatus(1); // 已确认
            association.setStatus(SystemStatusEnum.ENABLED.getCode());
            
            // 设置创建信息
            Long userId = SecurityUtils.getCurrentUserId();
            association.setCreateBy(userId);
            association.setUpdateBy(userId);
            
            // 保存关联关系
            boolean saved = ownerHouseholdService.save(association);
            if (!saved) {
                throw new BusinessException("保存业主房户关联关系失败");
            }
            
            log.info("创建业主房户关联关系成功，业主ID：{}，房户ID：{}", ownerId, householdId);
        } catch (Exception e) {
            log.error("创建业主房户关联关系失败，业主ID：{}，房户ID：{}", ownerId, householdId, e);
            throw new BusinessException("创建业主房户关联关系失败：" + e.getMessage());
        }
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Owner addOwnerWithHousehold(OwnerDTO ownerDTO, Long householdId) throws Exception {
        try {
            // 1. 处理业主信息（新增或更新）
            Owner owner = processOwnerInfo(ownerDTO);
            
            // 2. 建立房户关联关系
            createOwnerHouseholdAssociation(owner.getId(), householdId);
            
            log.info("新增业主并关联房户成功，业主ID：{}，房户ID：{}", owner.getId(), householdId);
            return owner;
        } catch (Exception e) {
            log.error("新增业主并关联房户失败，身份证号：{}，房户ID：{}", ownerDTO.getIdCard(), householdId, e);
            throw new BusinessException("新增业主并关联房户失败：" + e.getMessage());
        }
    }
    
    @Override
    public boolean checkAssociationExists(Long ownerId, Long householdId) throws Exception {
        try {
            // 查询是否存在关联关系
            OwnerHousehold association = ownerHouseholdService.getByOwnerIdAndHouseholdId(ownerId, householdId);
            return association != null;
        } catch (Exception e) {
            log.error("检查业主房户关联关系失败，业主ID：{}，房户ID：{}", ownerId, householdId, e);
            throw new BusinessException("检查业主房户关联关系失败：" + e.getMessage());
        }
    }
    
    /**
     * 创建新业主
     * 
     * @param ownerDTO 业主信息DTO
     * @return 新创建的业主
     * @throws Exception 创建异常
     */
    private Owner createNewOwner(OwnerDTO ownerDTO) throws Exception {
        // 再次检查业主是否已存在（防止并发情况）
        Owner existingOwner = ownerService.getOwnerByIdCard(ownerDTO.getIdCard());
        if (existingOwner != null) {
            log.info("业主已存在，返回现有业主，业主ID：{}，身份证号：{}", existingOwner.getId(), existingOwner.getIdCard());
            return existingOwner;
        }
        
        // 1. 根据身份证号查询用户，如果查到了，则填入所有对应的信息
        UserDTO existingUser = null;
        if (StringUtils.hasText(ownerDTO.getIdCard())) {
            try {
                existingUser = userFeignService.getUserByIdCard(ownerDTO.getIdCard());
                if (existingUser != null) {
                    log.info("根据身份证号找到用户，用户ID：{}，身份证号：{}", existingUser.getId(), ownerDTO.getIdCard());
                    // 填入用户信息到业主信息中
                    fillOwnerInfoFromUser(ownerDTO, existingUser);
                }
            } catch (Exception e) {
                log.warn("根据身份证号查询用户失败，身份证号：{}，错误：{}", ownerDTO.getIdCard(), e.getMessage());
            }
        }
        
        // 2. 如果身份证号查询不到用户，则直接新增用户（业主必须有身份证号，不需要再根据手机号查询）
        if (existingUser == null && StringUtils.hasText(ownerDTO.getPhone())) {
            try {
                Long newUserId = createNewUser(ownerDTO);
                if (newUserId != null) {
                    log.info("创建新用户成功，用户ID：{}，手机号：{}", newUserId, ownerDTO.getPhone());
                    existingUser = new UserDTO();
                    existingUser.setId(newUserId);
                }
            } catch (Exception e) {
                log.error("创建新用户失败，手机号：{}，错误：{}", ownerDTO.getPhone(), e.getMessage());
                throw new BusinessException("创建用户失败：" + e.getMessage());
            }
        }
        
        Owner newOwner = new Owner();
        BeanUtils.copyProperties(ownerDTO, newOwner);
        
        // 设置默认状态
        newOwner.setStatus(SystemStatusEnum.ENABLED.getCode());
        newOwner.setOwnerStatus(1); // 已激活
        
        // 设置创建信息
        Long userId = SecurityUtils.getCurrentUserId();
        newOwner.setCreateBy(userId);
        newOwner.setUpdateBy(userId);
        
        try {
            // 保存业主信息
            boolean saved = ownerService.save(newOwner);
            if (!saved) {
                throw new BusinessException("保存业主信息失败");
            }
            
            // 3. 更新业主表的user_id字段关联
            if (existingUser != null) {
                try {
                    newOwner.setUserId(existingUser.getId());
                    boolean updated = ownerService.updateById(newOwner);
                    if (updated) {
                        log.info("更新业主用户关联成功，业主ID：{}，用户ID：{}", newOwner.getId(), existingUser.getId());
                    } else {
                        log.warn("更新业主用户关联失败，业主ID：{}，用户ID：{}", newOwner.getId(), existingUser.getId());
                    }
                } catch (Exception e) {
                    log.error("更新业主用户关联异常，业主ID：{}，用户ID：{}，错误：{}", newOwner.getId(), existingUser.getId(), e.getMessage());
                    // 不抛出异常，业主创建成功，关联更新失败不影响业主创建
                }
            }
            
            // 4. 处理用户角色关联
            if (existingUser != null) {
                try {
                    // 检查用户是否已经有业主角色
                    List<String> userRoles = getUserRolesFromUserService(existingUser.getId());
                    if (userRoles == null || !userRoles.contains(RoleCodeEnum.OWNER.getCode())) {
                        // 为用户分配业主角色（角色ID=15）
                        List<Long> roleIds = new ArrayList<>();
                        roleIds.add(15L); // 业主角色ID
                        userFeignService.assignUserRoles(existingUser.getId(), roleIds);
                        log.info("为用户分配业主角色成功，用户ID：{}", existingUser.getId());
                    } else {
                        log.info("用户已有业主角色，无需重复分配，用户ID：{}", existingUser.getId());
                    }
                } catch (Exception e) {
                    log.error("为用户分配业主角色失败，用户ID：{}，错误：{}", existingUser.getId(), e.getMessage());
                    // 不抛出异常，业主创建成功，角色分配失败不影响业主创建
                }
            }
            
            log.info("创建新业主成功，业主ID：{}，身份证号：{}", newOwner.getId(), newOwner.getIdCard());
            return newOwner;
        } catch (Exception e) {
            // 如果保存失败，再次检查是否是因为并发创建导致的
            if (e.getMessage() != null && e.getMessage().contains("Duplicate entry") && e.getMessage().contains("id_card")) {
                log.warn("业主创建失败，可能是并发创建导致的，重新查询现有业主，身份证号：{}", ownerDTO.getIdCard());
                Owner concurrentOwner = ownerService.getOwnerByIdCard(ownerDTO.getIdCard());
                if (concurrentOwner != null) {
                    log.info("找到并发创建的业主，返回现有业主，业主ID：{}，身份证号：{}", concurrentOwner.getId(), concurrentOwner.getIdCard());
                    return concurrentOwner;
                }
            }
            throw e;
        }
    }
    
    /**
     * 更新现有业主信息
     * 
     * @param existingOwner 现有业主
     * @param ownerDTO 业主信息DTO
     * @return 更新后的业主
     * @throws Exception 更新异常
     */
    private Owner updateExistingOwner(Owner existingOwner, OwnerDTO ownerDTO) throws Exception {
        // 检查手机号是否发生变化
        boolean phoneChanged = !StringUtils.hasText(existingOwner.getPhone()) && StringUtils.hasText(ownerDTO.getPhone()) ||
                              StringUtils.hasText(existingOwner.getPhone()) && !existingOwner.getPhone().equals(ownerDTO.getPhone());
        
        if (phoneChanged) {
            log.info("业主手机号发生变化，原手机号：{}，新手机号：{}", existingOwner.getPhone(), ownerDTO.getPhone());
            
            // 如果原业主手机号为空，直接更新为新手机号
            if (!StringUtils.hasText(existingOwner.getPhone())) {
                existingOwner.setPhone(ownerDTO.getPhone());
                log.info("更新业主手机号，业主ID：{}，新手机号：{}", existingOwner.getId(), ownerDTO.getPhone());
            } else {
                // 如果原业主手机号不为空，将新手机号添加到备注中
                String newRemark = StringUtils.hasText(existingOwner.getRemark()) ? 
                    existingOwner.getRemark() + "；新手机号：" + ownerDTO.getPhone() :
                    "新手机号：" + ownerDTO.getPhone();
                existingOwner.setRemark(newRemark);
                log.info("将新手机号添加到备注，业主ID：{}，新手机号：{}", existingOwner.getId(), ownerDTO.getPhone());
            }
        }
        
        // 更新其他信息（除了身份证号）
        if (StringUtils.hasText(ownerDTO.getOwnerName())) {
            existingOwner.setOwnerName(ownerDTO.getOwnerName());
        }
        if (StringUtils.hasText(ownerDTO.getEmail())) {
            existingOwner.setEmail(ownerDTO.getEmail());
        }
        if (ownerDTO.getGender() != null) {
            existingOwner.setGender(ownerDTO.getGender());
        }
        if (ownerDTO.getBirthDate() != null) {
            existingOwner.setBirthDate(ownerDTO.getBirthDate());
        }
        if (StringUtils.hasText(ownerDTO.getAddress())) {
            existingOwner.setAddress(ownerDTO.getAddress());
        }
        if (StringUtils.hasText(ownerDTO.getOccupation())) {
            existingOwner.setOccupation(ownerDTO.getOccupation());
        }
        if (StringUtils.hasText(ownerDTO.getCompany())) {
            existingOwner.setCompany(ownerDTO.getCompany());
        }
        if (StringUtils.hasText(ownerDTO.getEmergencyContact())) {
            existingOwner.setEmergencyContact(ownerDTO.getEmergencyContact());
        }
        if (StringUtils.hasText(ownerDTO.getEmergencyPhone())) {
            existingOwner.setEmergencyPhone(ownerDTO.getEmergencyPhone());
        }
        
        // 设置更新信息
        Long userId = SecurityUtils.getCurrentUserId();
        existingOwner.setUpdateBy(userId);
        existingOwner.setUpdateTime(LocalDateTime.now());
        
        // 保存更新
        boolean updated = ownerService.updateById(existingOwner);
        if (!updated) {
            throw new BusinessException("更新业主信息失败");
        }
        
        log.info("更新业主信息成功，业主ID：{}，身份证号：{}", existingOwner.getId(), existingOwner.getIdCard());
        return existingOwner;
    }
    
    /**
     * 从用户信息填充业主信息
     * 
     * @param ownerDTO 业主DTO
     * @param userDTO 用户DTO
     */
    private void fillOwnerInfoFromUser(OwnerDTO ownerDTO, UserDTO userDTO) {
        if (userDTO == null) {
            return;
        }
        
        // 如果业主DTO中某些字段为空，则从用户DTO中填充
        if (!StringUtils.hasText(ownerDTO.getOwnerName()) && StringUtils.hasText(userDTO.getRealName())) {
            ownerDTO.setOwnerName(userDTO.getRealName());
        }
        if (!StringUtils.hasText(ownerDTO.getPhone()) && StringUtils.hasText(userDTO.getPhone())) {
            ownerDTO.setPhone(userDTO.getPhone());
        }
        if (!StringUtils.hasText(ownerDTO.getEmail()) && StringUtils.hasText(userDTO.getEmail())) {
            ownerDTO.setEmail(userDTO.getEmail());
        }
        if (ownerDTO.getGender() == null && userDTO.getGender() != null) {
            ownerDTO.setGender(userDTO.getGender());
        }
        if (ownerDTO.getBirthDate() == null && userDTO.getBirthday() != null) {
            // 注意：这里需要根据实际的日期格式进行转换
            // ownerDTO.setBirthDate(userDTO.getBirthday());
        }
    }
    
    /**
     * 创建新用户
     * 
     * @param ownerDTO 业主DTO
     * @return 新用户ID
     * @throws Exception 统一异常
     */
    private Long createNewUser(OwnerDTO ownerDTO) throws Exception {
        if (!StringUtils.hasText(ownerDTO.getPhone())) {
            throw new BusinessException("手机号不能为空，无法创建用户");
        }
        
        NormalUserCreateDTO userCreateDTO = new NormalUserCreateDTO();
        userCreateDTO.setUsername(ownerDTO.getPhone()); // 用户名使用手机号
        userCreateDTO.setPassword(ownerDTO.getPhone()); // 密码使用手机号
        userCreateDTO.setPhone(ownerDTO.getPhone());
        userCreateDTO.setRealName(ownerDTO.getOwnerName());
        userCreateDTO.setIdCard(ownerDTO.getIdCard());
        userCreateDTO.setEmail(ownerDTO.getEmail());
        userCreateDTO.setGender(ownerDTO.getGender());
        if (ownerDTO.getBirthDate() != null) {
            // 注意：NormalUserCreateDTO的setBirthday可能接受String类型
            userCreateDTO.setBirthday(ownerDTO.getBirthDate().toString());
        }
        userCreateDTO.setOperatorId(SecurityUtils.getCurrentUserId());
        
        Long userId = userFeignService.createNormalUser(userCreateDTO);
        log.info("创建新用户成功，用户ID：{}，手机号：{}", userId, ownerDTO.getPhone());
        
        // 新增用户后，立即设置用户类型为业主
        try {
            userFeignService.updateUserType(userId, RoleCodeEnum.OWNER.getCode());
            log.info("设置用户类型为业主成功，用户ID：{}", userId);
        } catch (Exception e) {
            log.warn("设置用户类型为业主失败，用户ID：{}，错误：{}", userId, e.getMessage());
            // 不抛出异常，用户创建成功，类型设置失败不影响业主创建
        }
        
        return userId;
    }
    
    /**
     * 从用户服务获取用户角色列表
     * 
     * @param userId 用户ID
     * @return 用户角色列表
     */
    private List<String> getUserRolesFromUserService(Long userId) {
        try {
            List<String> roleCodes = userFeignService.getUserRoles(userId).stream()
                .map(role -> role.getRoleCode())
                .collect(java.util.stream.Collectors.toList());
            return roleCodes;
        } catch (Exception e) {
            log.warn("获取用户角色失败，用户ID：{}，错误：{}", userId, e.getMessage());
            return null;
        }
    }
}
